package com.sg.business.permission.ui.column;

import java.util.List;

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckboxCellEditor;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;

import com.mobnut.commons.util.Utils;
import com.sg.business.permission.model.ActionDefinition;
import com.sg.business.permission.model.PermissionAction;
import com.sg.business.permission.model.ActionDefinition.CascadeActions;
import com.sg.widgets.ImageResource;
import com.sg.widgets.Widgets;

public abstract class AbstractCheckColumn {

	private boolean isEditable;

	public TableViewerColumn create(final TableViewer viewer) {
		TableViewerColumn column = new TableViewerColumn(viewer, SWT.CENTER);
		column.getColumn().setWidth(50);
		column.getColumn().setMoveable(true);
		column.getColumn().setAlignment(SWT.CENTER);
		column.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				return "";
			}

			@Override
			public Image getImage(Object element) {
				if (isTrue((PermissionAction) element)) {
					return Widgets.getImage(ImageResource.CHECKED_16);
				} else {
					return Widgets.getImage(ImageResource.UNCHECKED_16);
				}
			}
		});

		final CellEditor cellEditor = new CheckboxCellEditor(viewer.getTable());
		column.setEditingSupport(new EditingSupport(viewer) {

			@Override
			protected void setValue(Object element, Object value) {
				AbstractCheckColumn.this.setValue(viewer,
						(PermissionAction) element, Boolean.TRUE.equals(value));
			}

			@Override
			protected Object getValue(Object element) {
				return isTrue((PermissionAction) element);
			}

			@Override
			protected CellEditor getCellEditor(Object element) {
				return cellEditor;
			}

			@Override
			protected boolean canEdit(Object element) {
				return AbstractCheckColumn.this.canEdit(viewer,
						(PermissionAction) element);
			}
		});
		return column;
	}

	@SuppressWarnings("unchecked")
	protected void setValue(TableViewer viewer, PermissionAction thisAction,
			boolean value) {
		ActionDefinition thisActionDefinition = thisAction
				.getActionDefinition();
		CascadeActions[] cascadeActionsArray = thisActionDefinition
				.getCascadeActions(thisAction.getPermission());
		String[] regrantCodes = thisActionDefinition
				.getCascadeRegrantActionCodes();

		List<PermissionAction> permissionActions = (List<PermissionAction>) viewer
				.getInput();

		for (int i = 0; i < permissionActions.size(); i++) {
			PermissionAction otherAction = permissionActions.get(i);
			if (otherAction == thisAction) {
				continue;
			}
			String[] codes;
			String otherActionCode = otherAction.getActionDefinition()
					.getCode();
			if (cascadeActionsArray != null) {
				for (int j = 0; j < cascadeActionsArray.length; j++) {
					CascadeActions cascadeActions = cascadeActionsArray[j];
					if (cascadeActions == null) {
						codes = null;
					} else {
						codes = cascadeActions.getCascadeActionCodes();
					}

					if (Utils.inArray(otherActionCode, codes)) {
						String[] changedablePermission = cascadeActions
								.getChangedablePermission();
						String otherPermission = otherAction.getPermission();
						if (Utils.inArray(otherPermission,
								changedablePermission)) {
							otherAction.setPermission(cascadeActions
									.getCascadePermission());
						}
					}
				}
			}

			if (Utils.inArray(otherActionCode, regrantCodes)) {
				otherAction.setReGrantPermission(thisAction
						.getReGrantPermission());
			}
		}

		viewer.refresh();
	}

	protected abstract boolean isTrue(PermissionAction action);

	public boolean isEditable() {
		return isEditable;
	}

	public void setEditable(boolean isEditable) {
		this.isEditable = isEditable;
	}

	protected boolean canEdit(TableViewer viewer, PermissionAction action) {
		return isEditable();
	}

}
